package com.guanzhi.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

import static org.springframework.security.config.Customizer.withDefaults;

/**
 * SpringSecurity
 * <p> Package: com.guanzhi.controller </p>
 * <p> File: HelloController.java </p>
 * <p> Description:  (初探门径 SpringSecurity)</p>
 * <p> Date: 2024/3/16 21:48</p>
 *
 * @author 观之
 * @version 1.0 （代码版本）
 * @email <a href="mailto:guanzhi55634@aliyun.com">观之</a>（邮箱）
 * @date 2024/1/23 21:48
 * @since jdk17（jdk版本）
 */
@Configuration //声明类是一个配置类
@EnableWebSecurity //开启SpringSecurity的自定义配置
@EnableMethodSecurity //开启基于方法的授权
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        //httpSecurity.authorizeRequests(); 被标识后期版本后移除,推荐使用authorizeHttpRequests()方式;
        //httpSecurity.authorizeHttpRequests(); 将于6.1版本后彻底移除 建议使用authorizeHttpRequests(Customizer)方式;

        httpSecurity.authorizeHttpRequests(defaultRequestMatcher -> {
                    //anyRequest() 对所有请求开启授权保护
                    //authenticated() 已认证的请求会被自动授权
                    defaultRequestMatcher.anyRequest().authenticated();
                })
                //.formLogin(withDefaults()) //开启表单授权登录方式
                .formLogin(form -> {
                    form.loginPage("/login").permitAll() //设置登录页面,permitAll()采用无需授权方式即可访问当前页面;
                            //源码中UsernamePasswordAuthenticationFilter默认了username和password参数名;所以需要更改的需要实现如下内容:
                            .usernameParameter("username") //配置登录页面的表单用户名参数名,默认是username;
                            .passwordParameter("password") //配置登录页面的表单密码参数名,默认是password;
                            .failureUrl("/login?error") //登录失败返回的地址
                    //定义一个自定义的认证成功处理器MyAuthenticationSuccessHandler来处理用户认证成功后的逻辑;
                    //.successHandler(new MyAuthenticationSuccessHandler())
                    //定义一个自定义的认证失败处理器MyAuthenticationFailureHandler来处理用户认证失败后的逻辑;
                    //.failureHandler(new MyAuthenticationFailureHandler())
                    ;
                })
                .httpBasic(withDefaults()); //使用基于浏览器授权的方式

        //登出注销处理
        //httpSecurity.logout(logout -> {
            //定义一个自定义的认证成功处理器MyLogoutSuccessHandler来处理用户注销成功后的逻辑;
            //logout.logoutSuccessHandler(new MyLogoutSuccessHandler());
        //});

        //异常处理
        httpSecurity.exceptionHandling(exception -> {
            //定义一个自定义的处理器MyAuthenticationEntryPoint来处理用户未认证的逻辑;
            //exception.authenticationEntryPoint(new MyAuthenticationEntryPoint());
            //定义一个自定义的处理器MyAccessDeniedHandler来处理访问被拒绝的逻辑;
            //exception.accessDeniedHandler(new MyAccessDeniedHandler());
        });

        //会话并发处理
        //httpSecurity.sessionManagement(session -> {
            //session.maximumSessions(1) 设置登录的最大登录数;即不同的客户端登录相同的账户只允许登录一个;
            //定义一个自定义的会话过期策略MySessionInformationExpiredStrategy来处理用户会话过期后的逻辑;
            //session.maximumSessions(1).expiredSessionStrategy(new MySessionInformationExpiredStrategy());
        //});

        //跨域;开启默认的跨域处理
        //httpSecurity.cors(withDefaults());
        //csrf：跨站请求伪造攻击
        //httpSecurity.csrf(AbstractHttpConfigurer::disable);
        return httpSecurity.build();
    }
}
